// ARMware - an ARM emulator
// Copyright (C) <2007>  Wei Hu <wei.hu.tw@gmail.com>
// 
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#if TRACE_POWER_MGR
#include <iostream>
#endif

#include <cassert>
#include "PowerManager.hpp"

namespace ARMware
{
  //////////////////////////////// Public /////////////////////////////////////
  //============================== Operation ==================================
  
  void
  PowerManager::reset()
  {
    mPMCR = 0;
    mPCFR = 0;
    mPPCR = 0;
    mPWER = 3;
    mPSSR = 0;
    
    // :NOTE: Wei 2003-Dec-11:
    //
    // I assume all of the bits which have unknown values when reset have value 0.
    mPGSR = 0;
    
    // :NOTE: Wei 2004-Jan-16:
    //
    // Because ARMware is not a real machine, thus I should set OOK bit in the
    // POSR register after reset immediately.
    mPOSR = POSR_OOK;
  }
  
  template<>
  uint32_t
  PowerManager::get_data(uint32_t const address) const
  {
#if TRACE_POWER_MGR
    g_log_file << "POWER MGR: get value at address: " << std::hex << address << std::endl;
#endif
    
    switch (address)
    {
    case PMCR: return mPMCR;
    case PSSR: return mPSSR;
    case PSPR: return mPSPR;
    case PWER: return mPWER;
    case PCFR: return mPCFR;
    case PPCR: return mPPCR;
    case PGSR: return mPGSR;
    case POSR: return mPOSR;
      
    default:
      assert(!"Should not reach here.");
      return 0;
    }
  }
  
  template<>
  void
  PowerManager::put_data(uint32_t const address, uint32_t const value)
  {
#if TRACE_POWER_MGR
    g_log_file << "POWER MGR: put value " << std::hex << value << " at address " << address << std::endl;
#endif
    
    switch (address)
    {
    case PMCR: mPMCR = value; break;
    case PSSR: mPSSR = value; break;
    case PSPR: mPSPR = value; break;
    case PWER: mPWER = value; break;
    case PCFR: mPCFR = value; break;
      
    case PPCR:
      // :SA-1110 Developer's Manual: Wei 2004-Jan-11:
      //
      // The PPCR contains bits used to configure the core operating frequency generated by the PLL.
      //
      // :NOTE: Wei 2004-Jan-11:
      //
      // However, I enforce the core operating frequency as 206 MHz.
      // Thus, this register is no use to me.
      mPPCR = value;
      break;
      
    case PGSR: mPGSR = value; break;
    case POSR: assert(!"Should not reach here."); break;
    default: assert(!"Should not reach here."); break;
    }
  }
}
